import sys
import signal
from getpass import getpass
from gmusicapi.api import Api
from time import time

def init(email=None, password=None):
    api = Api()

    logged_in = False
    attempts = 0

    while not logged_in and attempts < 3:
        if email is None:
            email = raw_input("Email: ")
        if password is None or attempts > 0:
            password = getpass()

        logged_in = api.login(email, password)
        attempts += 1

    return api, logged_in

def isDuplicateSong(song1=None, song2=None):

    if song1 is None or song2 is None:
        return False

    # If the id is the same, they are not duplicated; they are the same song.
    if song1["id"] == song2["id"]:
        return False

    if song1["titleNorm"] != song2["titleNorm"]:
        return False

    if song1["artistNorm"] != song2["artistNorm"]:
        return False
    
    if song1["albumNorm"] != song2["albumNorm"]:
        return False

    durationDiff = song1["durationMillis"] - song2["durationMillis"]
    if abs(durationDiff) > 2000:
        return False

    return True

def isSongPurchased(song):
    if song is None:
        return False

    if "storeID" in song:
        if len(song["storeID"]):
            return True
    return False;


def main():
    import optparse
    parser = optparse.OptionParser()
    parser.add_option("-e", "--email", dest="email",
        help="Your GMail address.")
    parser.add_option("-p", "--password", dest="password",
        help="You GMail password or application specific password.")
    (options, args) = parser.parse_args()

    api, success = init(email=options.email, password=options.password)
    if success:
        print "Logged in, getting list of all songs ..."
    else:
        print "Couldn't log in :("
        return

    allSongs = api.get_all_songs()
    numberOfSongs = len(allSongs)

    if not numberOfSongs:
        print "Nothing found :("
        return

    print "Found %d song(s). Checking for duplicates ..." % numberOfSongs
    songIdsToDelete = list()

    songFormat = "%(artist)s, %(album)s, %(track)s - %(title)s (%(durationMillis)s ms, id:%(id)s)"

    incrementStartTime = time()
    for firstCounter, firstSong in enumerate(allSongs):

        incrementTime = (time() - incrementStartTime)
        if incrementTime > 5:
            print "----- Checked %d songs" % firstCounter, ", %d to go." % (numberOfSongs-firstCounter)
            incrementStartTime = time()
            
        if not firstSong["deleted"]:

            #Get list of songs _after_ this one (no need to check the ones before this
            # as they will have been checked earlier
            for secondCounter, secondSong in enumerate(allSongs[(firstCounter+1):]):
                
                if not secondSong["deleted"] and isDuplicateSong(firstSong, secondSong):
                    print "\n"
                    print "[%d]\t" % firstCounter, songFormat % firstSong
                    print "[%d]\t" % (firstCounter+1+secondCounter), songFormat % secondSong

                    #Which of the two duplicated songs to delete?
                    if isSongPurchased(firstSong) and isSongPurchased(secondSong):
                        #do nothing, they are both purchased songs!
                        pass
                    elif isSongPurchased(firstSong) :
                        #first firstSong is purchased, delete the second one
                        songIdsToDelete.append(secondSong["id"])
                    elif isSongPurchased(secondSong):
                        #second firstSong is purchased, delete the first one
                        songIdsToDelete.append(firstSong["id"])
                    elif firstSong["creationDate"] > secondSong["creationDate"]:
                        #first firstSong was uploaded later, delete the second one
                        songIdsToDelete.append(secondSong["id"])
                    else:
                        #second firstSong was uploaded later, delete the first one
                        songIdsToDelete.append(firstSong["id"])

    print "\n"
    if len(songIdsToDelete):
        print "Found %d duplicates." % len(songIdsToDelete)
    else:
        print "No duplicates."
        return

    doDeletion = raw_input("Delete duplicates? [N]")
    if doDeletion[:1].lower() == "y":
        for songId in songIdsToDelete:
            print "Delete %s:" % songId, "%s" % api.delete_songs(songId)
    
     
if __name__ == '__main__':
    main()
